package com.yanqu.road.server.manger.hunt;

import com.yanqu.road.entity.log.LogHuntBox;
import com.yanqu.road.logic.bussiness.player.UserHuntBussiness;
import com.yanqu.road.logic.config.GameConfig;
import com.yanqu.road.entity.config.hunt.HuntBoxReward;
import com.yanqu.road.entity.enums.eHuntMessageType;
import com.yanqu.road.entity.enums.eLogMoneyType;
import com.yanqu.road.entity.enums.eSystemId;
import com.yanqu.road.entity.hunt.HuntBox;
import com.yanqu.road.entity.hunt.OpenHuntBoxResult;
import com.yanqu.road.entity.hunt.UserHunt;
import com.yanqu.road.entity.message.WorldMessage;
import com.yanqu.road.entity.player.UserInfo;
import com.yanqu.road.pb.hunt.HuntProto;
import com.yanqu.road.pb.player.PlayerProto;
import com.yanqu.road.server.TempMgr;
import com.yanqu.road.server.GameServer;
import com.yanqu.road.server.gameplayer.GamePlayer;
import com.yanqu.road.server.gameplayer.module.hunt.HuntModule;
import com.yanqu.road.server.gameplayer.module.player.CurrencyModule;
import com.yanqu.road.server.manger.ConfigMgr;
import com.yanqu.road.server.manger.config.HuntConfigMgr;
import com.yanqu.road.server.manger.config.SystemOpenMgr;
import com.yanqu.road.server.manger.log.AutoLogMgr;
import com.yanqu.road.server.manger.log.LogMgr;
import com.yanqu.road.server.manger.player.WorldMessageMgr;
import com.yanqu.road.server.manger.player.GamePlayerMgr;
import com.yanqu.road.server.pb.HuntPb;
import com.yanqu.road.server.pb.PlayerPb;
import com.yanqu.road.server.protocol.GameErrorCode;
import com.yanqu.road.server.protocol.Protocol;
import com.yanqu.road.utils.LocalDateTimeHelper;
import com.yanqu.road.utils.UUIDHelper;
import com.yanqu.road.utils.property.Property;
import com.yanqu.road.utils.property.PropertyHelper;
import com.yanqu.road.utils.string.StringUtils;

import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

public class HuntMgr extends TempMgr {

    private static Map<String, HuntBox> huntBoxMap;

    private static final Object huntBoxLockObj = new Object();

    private static List<WorldMessage> huntMessageList;

    private static List<HuntProto.HuntMessageTempMsg.Builder> huntMessageMsgList;

    private static HashSet<Long> inSceneUserIdSet;

    private static long lastResetTime;

    @Override
    public boolean init() throws Exception {
        return reload();
    }

    @Override
    public boolean reloadConfig() throws Exception {
        return true;
    }

    @Override
    public boolean stop() {
        return false;
    }

    @Override
    public boolean save() {
        for(HuntBox huntBox : huntBoxMap.values()){
            if(huntBox.isInsertOption()){
                UserHuntBussiness.addHuntBox(huntBox);
            }else if(huntBox.isUpdateOption()){
                UserHuntBussiness.updateHuntBox(huntBox);
            }
        }
        List<WorldMessage> dataList = new ArrayList<>(huntMessageList);
        for(WorldMessage worldMessage : dataList){
            if(worldMessage.isInsertOption()){
                UserHuntBussiness.addHuntMessage(worldMessage);
            }
        }
        return true;
    }

    @Override
    public boolean reloadData() {
        inSceneUserIdSet = new HashSet<>();
        long zeroTime = LocalDateTimeHelper.getZeroTimeTimeStamp() / 1000;
        huntMessageList = UserHuntBussiness.getHuntMessageList(zeroTime);
        initHuntMessageMsg();
        huntBoxMap = UserHuntBussiness.getHuntBoxMap(zeroTime);
        lastResetTime = zeroTime;
        return true;
    }

    //每日重置
    public static void resetOneDay(){
        long zeroTime = LocalDateTimeHelper.getZeroTimeTimeStamp() / 1000;
        if(lastResetTime < zeroTime){
            inSceneUserIdSet = new HashSet<>();
            huntBoxMap = new ConcurrentHashMap<>();
            huntMessageList = new ArrayList<>();
            huntMessageMsgList = new ArrayList<>();
            UserHuntBussiness.deleteHuntMessage(zeroTime);
            lastResetTime = zeroTime;
        }
    }

    private static void initHuntMessageMsg(){
        List<HuntProto.HuntMessageTempMsg.Builder> msgList = new ArrayList<>();
        List<WorldMessage> messageList = new ArrayList<>(huntMessageList);
        messageList.sort((o1, o2) -> (int) (o1.getSendTime() - o2.getSendTime()));
        for(WorldMessage worldMessage : messageList){
            HuntProto.HuntMessageTempMsg.Builder msg = HuntPb.parseHuntMessageTempMsg(worldMessage);
            if(null != msg){
                msgList.add(msg);
            }
        }
        huntMessageMsgList = msgList;
    }

    public static void addUserInHuntScene(long userId){
        inSceneUserIdSet.add(userId);
    }

    public static void removeUserInHuntScene(long userId){
        inSceneUserIdSet.remove(userId);
    }

    public static List<HuntProto.HuntMessageTempMsg.Builder> getHuntMessageMsgList(){
        return new ArrayList<>(huntMessageMsgList);
    }

    private static void addHuntBoxNotify(GamePlayer player, HuntBox huntBox){
        huntMessageNotify(player, eHuntMessageType.HuntBoxShare.getValue(), player.getUserInfo().getCity(), player.getTitleId(), player.getUserInfo().getNickName(), huntBox.getHuntBoxUid(), huntBox.getGoodsBoxId());
    }

    private static void huntMessageNotify(GamePlayer player, int type, Object... str) {
        String content = WorldMessageMgr.encodeContent(str);
        huntMessageNotify(player, type, content);
    }

    private static void huntMessageNotify(GamePlayer player, int type, String content) {
        if (StringUtils.isNullOrEmpty(content)) {
            return;
        }
        if(!HuntConfigMgr.isInHuntBattleTime()){//不在时间内
            return;
        }
        HuntProto.HuntMessageTempMsg.Builder msg = HuntProto.HuntMessageTempMsg.newBuilder();
        msg.setType(type);
        msg.setSendTime(System.currentTimeMillis() / 1000);
        msg.setContent(content);
        if(null != player){
            UserInfo userInfo = player.getUserInfo();
            msg.setUserId(player.getUserId());
            PlayerProto.PlayerBaseTempMsg.Builder baseMsg = PlayerPb.parsePlayerBaseTempMsg(userInfo);
            msg.setPlayerBaseData(baseMsg);
        }
        addHuntMessageMsgToList(msg);
    }

    private static void addHuntMessageMsgToList(HuntProto.HuntMessageTempMsg.Builder msg){
        huntMessageMsgList.add(msg);
        sendHuntMessage(msg);
        addHuntMessage(msg);
    }

    private static void sendHuntMessage(HuntProto.HuntMessageTempMsg.Builder msg) {
        for(long userId : inSceneUserIdSet){
            GamePlayer player = GamePlayerMgr.getOnlinePlayer(userId);
            if(null != player){
                player.sendPacket(Protocol.U_HUNT_MESSAGE_SYNC, msg);
            }
        }
    }

    private static void addHuntMessage(HuntProto.HuntMessageTempMsg.Builder msg){
        if(null != msg){
            WorldMessage huntMessage = new WorldMessage();
            huntMessage.setType(msg.getType());
            huntMessage.setSendTime(msg.getSendTime());
            huntMessage.setContent(msg.getContent());
            huntMessage.setUserId(msg.getUserId());
            huntMessage.setInsertOption();
            huntMessageList.add(huntMessage);
        }
    }

    public static HuntBox addHuntBox(GamePlayer player, int huntBoxId){
        HuntBox huntBox;
        synchronized (huntBoxLockObj) {
            if(huntBoxMap.size() >= GameConfig.HUNT_ONE_DAY_MAX_OUTPUT_BOX_COUNT){//超过了就不产出了
                return null;
            }
            huntBox = new HuntBox();
            huntBox.setUserId(player.getUserId());
            huntBox.setHuntBoxUid(UUIDHelper.randomUUID(GameServer.getInstance().getServerId() + ""));
            huntBox.setCreateTime(System.currentTimeMillis() / 1000);
            huntBox.setGoodsBoxId(huntBoxId);
            huntBox.setHuntBoxRewardList(ConfigMgr.getHuntBoxRewardList());
            huntBox.setInsertOption();
            huntBoxMap.put(huntBox.getHuntBoxUid(), huntBox);
        }
        //增加全服通知
        addHuntBoxNotify(player, huntBox);
        return huntBox;
    }

    public static OpenHuntBoxResult openHuntBox(GamePlayer player, String huntBoxUid){
        OpenHuntBoxResult result = new OpenHuntBoxResult();
        if(!SystemOpenMgr.systemOpen(player, eSystemId.Hunt.getValue())){
            result.setRet(GameErrorCode.E_SYSTEM_NO_OPEN);
            return result;
        }
        if(!HuntConfigMgr.isHuntSystemOpenTime()){
            result.setRet(GameErrorCode.E_SYSTEM_NO_OPEN);
            return result;
        }
        if(!huntBoxMap.containsKey(huntBoxUid)){
            result.setRet(GameErrorCode.E_HUNT_BOX_NO_FOUND);
            return result;
        }
        UserHunt userHunt = player.getModule(HuntModule.class).getUserHunt();
        if(userHunt.isOpenHuntBox(huntBoxUid)){
            result.setRet(GameErrorCode.E_HUNT_BOX_HAS_OPEN);
            return result;
        }
        if(userHunt.getOpenBoxTimes() >= GameConfig.HUNT_DAILY_OPEN_BOX_COUNT){
            result.setRet(GameErrorCode.E_HUNT_BOX_TODAY_OPEN_TIMES_OVER);
            return result;
        }
        HuntBox huntBox = huntBoxMap.get(huntBoxUid);
        HuntBoxReward huntBoxReward;
        synchronized (huntBoxLockObj){
            if(huntBox.getHuntBoxRewardList() == null){
                huntBox.setHuntBoxRewardList(ConfigMgr.getHuntBoxRewardList());
            }
            if(huntBox.isUserOpenBox(player.getUserId())){
                result.setRet(GameErrorCode.E_HUNT_BOX_HAS_OPEN);
                return result;
            }
            huntBoxReward = HuntConfigMgr.getHuntBoxReward(huntBox);
            if(null == huntBoxReward) {
                result.setRet(GameErrorCode.E_HUNT_BOX_OPEN_TIMES_OVER);
                return result;
            }
            huntBox.addOpenUserId(player.getUserId());
            userHunt.addOpenHuntBox(huntBoxUid);
        }
        userHunt.setOpenBoxTimes(userHunt.getOpenBoxTimes() + 1);
        Property boxReward;
        int noticeType = 0;
        if(null != huntBoxReward){
            boxReward = huntBoxReward.getReward();
            noticeType = huntBoxReward.getNoticeType();
        }else {
            boxReward = new Property();
        }
        player.getModule(CurrencyModule.class).addCurrency(boxReward, eLogMoneyType.Hunt, eLogMoneyType.HuntOpenBox);
        String reward = PropertyHelper.parsePropertyToString(boxReward);
        result.setReward(reward);
        if(1 == noticeType){//加公告
            if(!StringUtils.isNullOrEmpty(reward)) {
                huntMessageNotify(player, eHuntMessageType.HuntBoxOpen.getValue(), player.getUserInfo().getCity(), player.getTitleId(),
                        player.getUserInfo().getNickName(), huntBox.getGoodsBoxId(), reward);
            }
        }
        player.getModule(HuntModule.class).syncHuntBoxData();
        AutoLogMgr.add(new LogHuntBox(player.getUserId(), huntBoxUid, huntBox.getGoodsBoxId(), reward));
        return result;
    }
}
